package com.hst.capacity.application.fence.biz.impl;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.hst.capacity.application.fence.biz.FenceBiz;
import com.hst.capacity.domain.exception.BusinessException;
import com.hst.capacity.domain.model.entity.setting.fence.FenceInfoEntity;
import com.hst.capacity.domain.model.request.fence.FenceAddParam;
import com.hst.capacity.domain.model.request.fence.FenceListParam;
import com.hst.capacity.domain.model.response.PagingResultVO;
import com.hst.capacity.domain.model.response.setting.fence.FenceInfoVO;
import com.hst.capacity.domain.model.response.setting.fence.pojo.Coordinate;
import com.hst.capacity.infra.convertor.SettingPriceConvertor;
import com.hst.capacity.infra.persistence.jpa.setting.fence.FenceInfoRepository;
import com.hst.capacity.infra.persistence.mybatis.FenceInfoMapper;
import com.hst.capacity.infra.util.StringUtil;
import com.hst.capacity.application.fence.util.FenceUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class FenceBizImpl implements FenceBiz {

    @Autowired
    private FenceInfoRepository fenceRepository;

    @Autowired
    private FenceInfoMapper fenceMapper;

    @Override
    public FenceInfoVO save(FenceAddParam param) {
        FenceInfoEntity entity;
        Integer idFence = null;
        String idFranchisee = null;
        String idBrand = null;
        if (StringUtil.isNotBlank(param.getIdFence())) {
            entity = fenceRepository.findByIdFence(Integer.parseInt(param.getIdFence()));
            if (entity == null)
                throw new BusinessException(5002, "未找到对应的围栏，请确认。");
            idFence = entity.getIdFence();
            idFranchisee = entity.getIdFranchisee();
            idBrand = entity.getIdBrand();
        }
        entity = SettingPriceConvertor.INSTANCE.convert(param);
        if (idFence != null) {
            entity.setIdFence(idFence);
            entity.setIdFranchisee(idFranchisee);
            entity.setIdBrand(idBrand);
        }
        entity = fenceRepository.save(entity);
        return SettingPriceConvertor.INSTANCE.convert(entity);
    }

    @Override
    public PagingResultVO<FenceInfoVO> search(FenceListParam param) {
        PagingResultVO<FenceInfoVO> result = new PagingResultVO<>(fenceMapper.searchTotal(param), fenceMapper.search(param));
        return result;
    }

    @Override
    public List<FenceInfoVO> searchList(FenceListParam param) {
        List<FenceInfoVO> list = fenceMapper.search(param);
        return list;
    }

    @Override
    public Integer newStatus(int idFence, int status) {
        FenceInfoEntity entity = fenceRepository.findByIdFence(idFence);
        if (entity == null)
            throw new BusinessException(5002, "未找到对应的围栏，请确认。");
        entity.setStatus(status);
        entity = fenceRepository.save(entity);
        return entity.getIdFence();
    }

    @Override
    public boolean isInFence(int idFence, String latitude, String longitude) {
        FenceInfoEntity entity = fenceRepository.findByIdFence(idFence);
        if (entity == null)
            return false;

        Point2D.Double point = new Point2D.Double(Double.parseDouble(latitude), Double.parseDouble(longitude));
        String scope = entity.getScope();
        JSONObject json = JSONObject.parseObject(scope);
        JSONArray circleArr = json.getJSONArray("circle");
        if (circleArr != null && circleArr.size() > 0) {
            for (int j = 0; j < circleArr.size(); j++) {
                JSONObject obj = circleArr.getJSONObject(j);
                String circle = obj.getString("center");
                double radius = obj.getDoubleValue("radius");
                Coordinate coordinate = JSON.parseObject(circle, Coordinate.class);
                Point2D.Double center = new Point2D.Double(coordinate.getLat(), coordinate.getLng());
                FenceUtil fenceUtil = new FenceUtil();
                if(fenceUtil.isInCircle(point, center, radius)){
                    return true;
                }
            }
        }

        // parse scope polygon to List<PolygonFence>
        JSONArray polygonArr = json.getJSONArray("polygon");
        if (polygonArr != null && polygonArr.size() > 0) {
            for (int j = 0; j < polygonArr.size(); j++) {
                JSONObject obj = polygonArr.getJSONObject(j);
                String path = obj.getString("paths");
                if (StringUtil.isNotBlank(path)) {
                    List<Point2D.Double> fencePoints = new ArrayList<>();
                    JSONArray array = JSONArray.parseArray(path);
                    List<Coordinate> coordinateArr = JSON.parseArray(array.toString(), Coordinate.class);
                    for (Coordinate coordinate : coordinateArr) {
                        fencePoints.add(new Point2D.Double(coordinate.getLat(), coordinate.getLng()));
                    }

                    FenceUtil fenceUtil = new FenceUtil();
                    if (fenceUtil.isInPolygon(point, fencePoints)){
                        //log.info("fun isInPolygon fencePoints:{}", JSON.toJSONString(fencePoints));
                        log.info("在范围内:{}", point.toString());
                        return true;
                    } else {
                        log.info("不在区域内:{}", point.toString());
                    }
                }
            }
        }

        return false;
    }

    /**
     * 判断出发地，目的地是否在限行围栏内，
     * 任一点在围栏内返回true
     * @param idFence
     * @param origins
     * @param dest
     * @return
     */
    @Override
    public boolean addressInFence(int idFence, String origins, String dest) {
        String[] pointOrigins = origins.split(",");
        boolean res = this.isInFence(idFence, pointOrigins[0], pointOrigins[1]);
        if (res)
            return true;

        String[] pointDest = dest.split(",");
        res = this.isInFence(idFence, pointDest[0], pointDest[1]);
        if (res)
            return true;

        return false;
    }

    /**
     * 判断出发地，目的地是否在限行围栏内，
     * 任一点不在围栏内返回false
     * @param idFence
     * @param origins
     * @param dest
     * @return
     */
    @Override
    public boolean addressNotInFence(int idFence, String origins, String dest) {
        String[] pointOrigins = origins.split(",");
        boolean res = this.isInFence(idFence, pointOrigins[0], pointOrigins[1]);
        if (!res)
            return false;

        String[] pointDest = dest.split(",");
        res = this.isInFence(idFence, pointDest[0], pointDest[1]);
        if (!res)
            return false;

        return true;
    }

}
